// basic
import json from 'koa-json';
import bodyParser from 'koa-bodyparser';
import Router from 'koa-router';
import compress from 'koa-compress';
import responseTime from 'koa-response-time';
import log4js from 'koa-log4';
import Koa from 'koa';
import cors from './app/middleware/cors';

// components
import componentContainer from './components/componentContainer';

// robots
import './app/robots';

// routes
import usersRouter from './app/api/users';
import groupsRouter from './app/api/groups';
import channelsRouter from './app/api/channels';
import messagesRouter from './app/api/messages';
import replyTemplateRouter from './app/api/replyTemplate';
import replyTemplateGroupRouter from './app/api/replyTemplateGroup';
import serverRouter from './app/api/server';
import internalRouter from './app/api/internal';
import suggestionRouter from './app/api/suggestion';
import queueRouter from './app/api/queue';
import aggregationRouter from './app/api/aggregation';


/**
 * Environment.
 */
const env = process.env.NODE_ENV || 'development';
const port = process.env.PORT || 5000;

/**
 * Better Error Stack.
 */
// global.Promise = bluebird;

/**
 * App logger.
 */
const httpLogger = log4js.getLogger('HTTP');

if (env === 'test') {
  log4js.loadAppender('console');
  log4js.addAppender(log4js.appenders.console());
} else {
  log4js.configure('./log4js_worker.json');
}


if (env === 'development') {
  log4js.loadAppender('console');
  log4js.addAppender(log4js.appenders.console());
}

process.on('unhandledRejection', (err) => {
  httpLogger.error(err);
});

/**
 * boot app.
 */
const app = new Koa();

// init component container
componentContainer.init(app);

// CORS
app.use(cors({
  credentials: true,
}));

// Global Error Handler
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    httpLogger.error(err);
    ctx.status = 500;
    ctx.body = {
      status: 500,
      name: err.name,
      message: err.message,
    };
  }
});

// Http logger
app.use(log4js.koaLogger(log4js.getLogger('http'), { level: 'auto' }));

// x-response-time
app.use(responseTime());
// compression
if (env === 'production') app.use(compress());

// form or json input
app.use(bodyParser());

// json response
app.use(json());

// inject redis and logger
app.use((ctx, next) => {
  ctx.redis = componentContainer.getRedis();
  ctx.logger = httpLogger;
  return next();
});

/**
 * routes
 */
const rootRouter = new Router();

rootRouter.get('/', async (ctx) => {
  ctx.body = 'This is jiuqu customer api server.';
});
rootRouter.options('*', async (ctx) => {
  ctx.body = { pk: true };
});
app.use(rootRouter.routes());
app.use(usersRouter.routes());
app.use(groupsRouter.routes());
app.use(channelsRouter.routes());
app.use(messagesRouter.routes());
app.use(replyTemplateRouter.routes());
app.use(replyTemplateGroupRouter.routes());
app.use(serverRouter.routes());
app.use(internalRouter.routes());
app.use(suggestionRouter.routes());
app.use(queueRouter.routes());
app.use(aggregationRouter.routes());

/**
 * Start app.
 */
if (process.env.NODE_ENV !== 'test') {
  app.listen(port, () => httpLogger.info(`server started ${port}`));
}

export default app;
